module ctrlpath
		(
		clock, resetn,

		zero,
		
		branch, decabnz,
		ioset, loadacc,
		swait,
		ramp, rsram, rlta,

		int_tmr,
		rDIPSW,
		
		load_pc, cnten_pc, sclr_pc,
		load_opc, load_opr,
		load_acc, cntdn_acc, sclr_acc,
		load_cntref, cnten_tmr, sclr_tmr,
		init_porta, load_porta, init_portb, load_portb,
		sel_portb, PBADDR
		);
input			clock, resetn;
input			zero;

input			branch, decabnz;
input			ioset, loadacc;
input			swait;
input			ramp, rsram, rlta;

input			int_tmr;
input	[3:0]	rDIPSW;

output			load_pc, cnten_pc, sclr_pc;
output			load_opc, load_opr;
output			load_acc, cntdn_acc, sclr_acc;
output			load_cntref, cnten_tmr, sclr_tmr;
output			init_porta, load_porta, init_portb, load_portb;
output			sel_portb;
output	[5:0]	PBADDR;

reg				load_pc, cnten_pc, sclr_pc;
reg				load_opc, load_opr;
reg				load_acc, cntdn_acc, sclr_acc;
reg				load_cntref, cnten_tmr, sclr_tmr;
reg				init_porta, load_porta, init_portb, load_portb;
reg				sel_portb;
reg		[5:0]	PBADDR;

wire			run;
assign			run = rDIPSW[3];

parameter [5:0] IDLE  = 0, FETCH = 1, DECODE = 2, WB = 3,
				brEXEC = 4,
				dbEXEC = 5, dbCHKA = 6, dbSETPC = 7,
				ioEXEC = 8,
				laEXEC = 9,
				waEXEC = 10, waWAIT = 11,
				raEXEC = 12, raINIT = 13, raLATCH = 14, raCOMPARE = 15,
				raFIN1 = 16, raFIN2 = 17, raFIN3 = 18,
				srEXEC = 19, srINIT = 20, srPRECH = 21, srSENSE = 22,
				srLATCH1 = 23, srWAIT1 = 24, srLATCH2 = 25, srWAIT2 = 26,
				srPODODD = 27,
				ltEXEC = 28, ltINIT1 = 29, ltINIT2 = 30, ltWAIT = 31,
				ltLATCH = 32,
				FIN = 33;
reg		[5:0]	STATE;

always @(posedge clock or negedge resetn)
begin: NEXT_CURR
	if (~resetn)	STATE <= IDLE;
	else
		case (STATE)
		IDLE:
			if (~run)
				STATE <= IDLE;
			else
				STATE <= FETCH;
		FETCH:	STATE <= DECODE;
		DECODE:
			if (branch)
				STATE <= brEXEC;
			else if (decabnz)
				STATE <= dbEXEC;
			else if (ioset)
				STATE <= ioEXEC;
			else if (loadacc)
				STATE <= laEXEC;
			else if (swait)
				STATE <= waEXEC;
			else if (ramp)
				STATE <= raEXEC;
			else if (rsram)
				STATE <= srEXEC;
			else if (rlta)
				STATE <= ltEXEC;
			else
				STATE <= IDLE;
		WB:
			if (~run)
				STATE <= IDLE;
			else
				STATE <= FETCH;
		brEXEC:	STATE <= WB;
		dbEXEC: STATE <= dbCHKA;
		dbCHKA:
			if (~zero)
				STATE <= dbSETPC;
			else
				STATE <= WB;
		dbSETPC: STATE <= WB;
		ioEXEC:	STATE <= WB;
		laEXEC: STATE <= WB;
		waEXEC: STATE <= waWAIT;
		waWAIT:
			if (~int_tmr)
				STATE <= waWAIT;
			else
				STATE <= WB;
		raEXEC:	STATE <= raINIT;
		raINIT:	STATE <= raLATCH;
		raLATCH: STATE <= raCOMPARE;
		raCOMPARE:
			if (~int_tmr)
				STATE <= raLATCH;
			else
				STATE <= raFIN1;
		raFIN1: STATE <= raFIN2;
		raFIN2: STATE <= raFIN3;
		raFIN3: STATE <= FIN;

		srEXEC: STATE <= srINIT;
		srINIT:	STATE <= srPRECH;
		srPRECH: STATE <= srSENSE;
		srSENSE: STATE <= srLATCH1;
		srLATCH1: STATE <= srWAIT1;
		srWAIT1: STATE <= srLATCH2;
		srLATCH2: STATE <= srWAIT2;
		srWAIT2: STATE <= srPODODD;
		srPODODD:
			if (~int_tmr)
				STATE <= srPRECH;
			else
				STATE <= FIN;
		ltEXEC: STATE <= ltINIT1;
		ltINIT1: STATE <= ltINIT2;
		ltINIT2: STATE <= ltWAIT;
		ltWAIT:	STATE <= ltLATCH;
		ltLATCH:
			if (~int_tmr)
				STATE <= ltWAIT;
			else
				STATE <= FIN;
		FIN:
			if (~run)
				STATE <= IDLE;
			else
				STATE <= FETCH;
		default: STATE <= IDLE;
		endcase
end

always @(STATE)
begin: OUT_LOGIC
	case (STATE)
	IDLE:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 1;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 1;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 1;
			init_porta   = 1;    init_portb    = 1;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	FETCH:
		begin
			load_pc      = 0;    cnten_pc      = 1;    sclr_pc   = 0;
			load_opc     = 1;    load_opr      = 1;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	DECODE:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	WB:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	brEXEC:
		begin
			load_pc      = 1;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	dbEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 1;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	dbCHKA:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	dbSETPC:
		begin
			load_pc      = 1;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	ioEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 1;    load_portb    = 1;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	laEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 1;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	waEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 1;    cnten_tmr     = 0;    sclr_tmr  = 1;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	waWAIT:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 1;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	raEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 1;    cnten_tmr     = 0;    sclr_tmr  = 1;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 1;
			PBADDR = 6'b00_0000;
		end
	raINIT:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0001;
		end
	raLATCH:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 1;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0010;
		end
	raCOMPARE:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0011;
		end
	raFIN1:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0100;
		end
	raFIN2:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0101;
		end
	raFIN3:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0110;
		end
	srEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 1;    cnten_tmr     = 0;    sclr_tmr  = 1;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 1;
			PBADDR = 6'b00_0000;
		end
	srINIT:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0001;
		end
	srPRECH:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 1;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0010;
		end
	srSENSE:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0011;
		end
	srLATCH1:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0100;
		end
	srWAIT1:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0101;
		end
	srLATCH2:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0110;
		end
	srWAIT2:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_0111;
		end
	srPODODD:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b01_1000;
		end
	ltEXEC:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 1;    cnten_tmr     = 0;    sclr_tmr  = 1;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 1;
			PBADDR = 6'b00_0000;
		end
	ltINIT1:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b10_0001;
		end
	ltINIT2:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b10_0010;
		end
	ltWAIT:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 1;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b10_0011;
		end
	ltLATCH:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b10_0100;
		end
	FIN:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 0;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 0;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 0;
			init_porta   = 0;    init_portb    = 0;
			load_porta   = 0;    load_portb    = 1;    sel_portb = 1;
			PBADDR = 6'b00_0000;
		end
	default:
		begin
			load_pc      = 0;    cnten_pc      = 0;    sclr_pc   = 1;
			load_opc     = 0;    load_opr      = 0;
			load_acc     = 0;    cntdn_acc     = 0;    sclr_acc  = 1;
			load_cntref  = 0;    cnten_tmr     = 0;    sclr_tmr  = 1;
			init_porta   = 1;    init_portb    = 1;
			load_porta   = 0;    load_portb    = 0;    sel_portb = 0;
			PBADDR = 6'b00_0000;
		end
	endcase
end
endmodule